﻿using System;
using System.Collections.Generic;
using System.Runtime.Serialization;

namespace Yunli.Entities
{
    /// <summary>
    /// 表示业务数据实体类。无法实例化该类。
    /// </summary>
    public abstract class BusinessEntity : ISerializable
    {
        public object this[string p_key]
        {
            get { return GetValue(p_key); }
            set { SetValue(p_key, value); }
        }

        public string ID
        {
            get
            {
                if (this["id"] == null)
                {
                    Data["id"] = Guid.NewGuid().ToString();
                }
                return this["id"].ToString();
            }
        }

        public string Name
        {
            get { return this["name"] as string; }
            set { this["name"] = value; }
        }

        private Dictionary<string, object> _data = new Dictionary<string, object>();
        protected Dictionary<string, object> Data
        {
            get { return _data; }
        }

        public virtual bool HasAttribute(string p_key)
        {
            return Data.ContainsKey(p_key);
        }

        public virtual object GetValue(string p_key)
        {
            return HasAttribute(p_key) ? Data[p_key] : null;
        }

        public virtual void SetValue(string p_key, object p_value)
        {
            var changed = false;
            if (GetValue(p_key) != p_value)
            {
                changed = true;
            }

            Data[p_key] = p_value;

            if (changed)
            {
                OnAttributeValueChanged(new ValueChangedEventArgs(p_key));
            }
        }

        public event ValueChangedEventHandler ValueChanged = null;

        /// <summary>
        /// 引发 ValueChanged 事件。
        /// </summary>
        /// <param name="e"></param>
        protected virtual void OnAttributeValueChanged(ValueChangedEventArgs e)
        {
            if (ValueChanged != null)
            {
                ValueChanged(this, e);
            }
        }

        public virtual bool GetBoolValue(string p_key, bool p_defaultValue)
        {
            return this[p_key] != null ? (bool)this[p_key] : p_defaultValue;
        }

        public virtual string GetStringValue(string p_key)
        {
            return this[p_key] != null ? this[p_key].ToString() : null;
        }

        public virtual int GetIntValue(string p_key)
        {
            return this[p_key] != null ? (int)this[p_key] : EmptyValue.Int;
        }

        public virtual long GetLongValue(string p_key)
        {
            return this[p_key] != null ? (long)this[p_key] : EmptyValue.Long;
        }

        public virtual double GetDoubleValue(string p_key)
        {
            return this[p_key] != null ? (double)this[p_key] : EmptyValue.Double;
        }

        public virtual float GetFloatValue(string p_key)
        {
            return this[p_key] != null ? (float)this[p_key] : EmptyValue.Float;
        }

        public virtual DateTime GetDateTimeValue(string p_key)
        {
            return this[p_key] != null ? (DateTime)this[p_key] : EmptyValue.DateTime;
        }

        public virtual TimeSpan GetTimeSpanValue(string p_key)
        {
            return this[p_key] != null ? (TimeSpan)this[p_key] : EmptyValue.TimeSpan;
        }

        public virtual void GetObjectData(SerializationInfo p_info, StreamingContext p_context)
        {
            Data.GetObjectData(p_info, p_context);
        }

        public override string ToString()
        {
            return Name;
        }
    }
}